package cn.jeasy.core.mvc;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.jeasy.core.bean.support.ClassScanner;
import cn.jeasy.core.mvc.annotation.Controller;
import cn.jeasy.core.mvc.annotation.RequestMapping;
import cn.jeasy.core.mvc.em.RequestMethod;
import cn.jeasy.core.util.ArrayUtil;
import cn.jeasy.core.util.CollectionUtil;
import cn.jeasy.core.util.StringUtil;

/**
 * 初始化 Action 配置
 *
 * @author Fred
 */
public class ActionHelper {
	 private static final Logger logger = LoggerFactory.getLogger(ActionHelper.class);
    /**
     * Action Map（HTTP 请求与 Action 方法的映射）
     */
    private static final Map<Requester, Handler> actionMap = new LinkedHashMap<Requester, Handler>();

    static {
        // 获取所有 Action 类
        List<Class<?>> actionClassList = ClassScanner.getInstance().getClassListByAnnotations("",Controller.class);
        if (CollectionUtil.isNotEmpty(actionClassList)) {
            // 定义两个 Action Map
            Map<Requester, Handler> commonActionMap = new HashMap<Requester, Handler>(); // 存放普通 Action Map
            Map<Requester, Handler> regexpActionMap = new HashMap<Requester, Handler>(); // 存放带有正则表达式的 Action Map
            // 遍历 Action 类
            for (Class<?> actionClass : actionClassList) {
                // 获取并遍历该 Action 类中所有的方法
                Method[] actionMethods = actionClass.getDeclaredMethods();
                if (ArrayUtil.isNotEmpty(actionMethods)) {
                    for (Method actionMethod : actionMethods) {
                    	if(actionMethod.isAnnotationPresent(RequestMapping.class)){
                    		// 处理 Action 方法
                            handleActionMethod(actionClass, actionMethod, commonActionMap, regexpActionMap);
                          }
                      }
                }
            }
            // 初始化最终的 Action Map（将 Common 放在 Regexp 前面）
            actionMap.putAll(commonActionMap);
            actionMap.putAll(regexpActionMap);
        }
    }

    private static void handleActionMethod(Class<?> actionClass, Method actionMethod, Map<Requester, Handler> commonActionMap, Map<Requester, Handler> regexpActionMap) {
    	String requestPath="";
    	// 判断当前 Action 方法是否带有 Request 注解
    	RequestMapping  klassRequestMapping=actionClass.getAnnotation(RequestMapping.class);
    	if(klassRequestMapping!=null&&StringUtil.isNotEmpty(klassRequestMapping.value())){
    		requestPath=klassRequestMapping.value();
    	}
    	RequestMapping  requestMapping=actionMethod.getAnnotation(RequestMapping.class);
    	RequestMethod[] methods=requestMapping.method();
    	if(StringUtil.isNotEmpty(requestMapping.value())){
    	  requestPath+=requestMapping.value();
    	}
    	for(RequestMethod m:methods){
    		 putActionMap(m.name(), requestPath, actionClass, actionMethod, commonActionMap, regexpActionMap);
    	}
       
    }

    private static void putActionMap(String requestMethod, String requestPath, Class<?> actionClass, Method actionMethod, Map<Requester, Handler> commonActionMap, Map<Requester, Handler> regexpActionMap) {
        // 判断 Request Path 中是否带有占位符
        if (requestPath.matches(".+\\{\\w+\\}.*")) {
            // 将请求路径中的占位符 {\w+} 转换为正则表达式 (\\w+)
            requestPath = StringUtil.replaceAll(requestPath, "\\{\\w+\\}", "(\\\\w+)");
            // 将 Requester 与 Handler 放入 Regexp Action Map 中
            regexpActionMap.put(new Requester(requestMethod, requestPath), new Handler(actionClass, actionMethod));
        } else {
            // 将 Requester 与 Handler 放入 Common Action Map 中
            commonActionMap.put(new Requester(requestMethod, requestPath), new Handler(actionClass, actionMethod));
        }
        logger.debug("requestMethod="+requestMethod+",requestPath="+requestPath+",actionClass="+actionClass);
    }

    /**
     * 获取 Action Map
     */
    public static Map<Requester, Handler> getActionMap() {
        return actionMap;
    }
}
